% !TEX TS-program = pdflatex
% !TEX encoding = UTF-8 Unicode

% This file is a template using the "beamer" package to create slides for a talk or presentation
% - Talk at a conference/colloquium.
% - Talk length is about 20min.
% - Style is ornate.

% MODIFIED by Jonathan Kew, 2008-07-06
% The header comments and encoding in this file were modified for inclusion with TeXworks.
% The content is otherwise unchanged from the original distributed with the beamer package.

\documentclass{beamer}


% Copyright 2004 by Till Tantau <tantau@users.sourceforge.net>.
%
% In principle, this file can be redistributed and/or modified under
% the terms of the GNU Public License, version 2.
%
% However, this file is supposed to be a template to be modified
% for your own needs. For this reason, if you use this file as a
% template and not specifically distribute it as part of a another
% package/program, I grant the extra permission to freely copy and
% modify this file as you see fit and even to delete this copyright
% notice. 


\mode<presentation>
{
\usetheme{Warsaw}
% or ...

\setbeamercovered{transparent}
% or whatever (possibly just delete it)
}


\usepackage[english]{babel}
% or whatever

\usepackage[utf8]{inputenc}
% or whatever

\usepackage{times}
\usepackage[T1]{fontenc}
% Or whatever. Note that the encoding and the font should match. If T1
% does not look nice, try deleting the line with the fontenc.


\title[Two Phase Commit in MongoDB] % (optional, use only with long paper titles)
{Two Phase Commit in MongoDB}


\author[Zhilei Ren] % (optional, use only with lots of authors)
{Zhilei Ren}
% - Give the names in the same order as the appear in the paper.
% - Use the \inst{?} command only if the authors have different
%   affiliation.

% This is only inserted into the PDF information catalog. Can be left
% out. 



% If you have a file called "university-logo-filename.xxx", where xxx
% is a graphic format that can be processed by latex or pdflatex,
% resp., then you can add a logo as follows:

% \pgfdeclareimage[height=0.5cm]{university-logo}{university-logo-filename}
% \logo{\pgfuseimage{university-logo}}



% Delete this, if you do not want the table of contents to pop up at
% the beginning of each subsection:


% If you wish to uncover everything in a step-wise fashion, uncomment
% the following command: 

%\beamerdefaultoverlayspecification{<+->}


\begin{document}

\begin{frame}
	\titlepage
\end{frame}



% Structuring a talk is a difficult task and the following structure
% may not be suitable. Here are some rules that apply for this
% solution: 

% - Exactly two or three sections (other than the summary).
% - At *most* three subsections per section.
% - Talk about 30s to 2min per frame. So there should be between about
%   15 and 30 frames, all told.

% - A conference audience is likely to know very little of what you
%   are going to talk about. So *simplify*!
% - In a 20min talk, getting the main ideas across is hard
%   enough. Leave out details, even if it means being less precise than
%   you think necessary.
% - If you omit details that are vital to the proof/implementation,
%   just say so once. Everybody will be happy with that.

\begin{frame}
	\begin{block}{Background}
		Operations on a single document are always atomic with MongoDB databases; however, operations that involve multiple documents, which are often referred to as "multi-document transactions", are not atomic. Since documents can be fairly complex and contain multiple "nested" documents, single-document atomicity provides the necessary support for many practical use cases.
	\end{block}
\end{frame}

\begin{frame}
	\begin{block}{Motivation}
		Despite the power of single-document atomic operations, there are cases that require multi-document transactions. When executing a transaction composed of sequential operations, certain issues arise, such as:
		\begin{enumerate}
			\item Atomicity: if one operation fails, the previous operation within the transaction must "rollback" to the previous state (i.e. the "nothing," in "all or nothing").
			\item Consistency: if a major failure (i.e. network, hardware) interrupts the transaction, the database must be able to recover a consistent state.
		\end{enumerate}
	\end{block}
\end{frame}

\begin{frame}
	\begin{block}{Overview}
		Consider a scenario where you want to transfer funds from account A to account B. In a relational database system, you can subtract the funds from A and add the funds to B in a single multi-statement transaction. In MongoDB, you can emulate a two-phase commit to achieve a comparable result.

		The examples in this tutorial use the following two collections:
		\begin{enumerate}
			\item A collection named accounts to store account information.
			\item A collection named transactions to store information on the fund transfer transactions
		\end{enumerate}
	\end{block}
\end{frame}

\begin{frame}
	\begin{block}{Initialize Source and Destination Accounts}
		Insert into the accounts collection a document for account A and a document for account B.
	\end{block}
	\pause
	\begin{alertblock}{Mongo shell}
		\scriptsize
		db.accounts.insert(\{name: "A", balance: 1000, pendingTransactions: []\})

		db.accounts.insert(\{name: "B", balance: 1000, pendingTransactions: []\})
db.accounts.find()
	\end{alertblock}
\end{frame}

\begin{frame}
	\begin{block}{Initialize Transfer Record}
		To initialize the transfer of 100 from account A to account B, insert into the transactions collection a document with the transfer information, the transaction state of "initial"

	\end{block}
	\pause
	\begin{alertblock}{Mongo shell}
		\scriptsize
		db.transactions.insert(\{source: "A", destination: "B", value: 100, state: "initial"\})
	\end{alertblock}
\end{frame}

\begin{frame}
	\begin{block}{Retrieve the transaction to start}
		From the transactions collection, find a transaction in the initial state. Currently the transactions collection has only one document, namely the one added in the Initialize Transfer Record step. If the collection contains additional documents, the query will return any transaction with an initial state unless you specify additional query conditions.
	\end{block}
	\pause
	\begin{alertblock}{Mongo shell}
		\scriptsize

		var t = db.transactions.findOne(\{state: "initial"\})
	\end{alertblock}
\end{frame}

\begin{frame}
	\begin{block}{Update transaction state to pending}
		Set the transaction state from initial to pending.
	\end{block}
	\pause
	\begin{alertblock}{Mongo shell}
		\scriptsize

		db.transactions.update(\{\_id: t.\_id\}, \{\$set: \{state: "pending"\}\})

		db.transactions.find()
	\end{alertblock}
\end{frame}

\begin{frame}
	\begin{block}{Apply the transaction to both accounts}
		To apply the transaction to the account, update both the balance field and the pendingTransactions field.

		Update the source account, subtracting from its balance the transaction value and adding to its pendingTransactions array the transaction \_id.

	\end{block}
	\pause
	\begin{alertblock}{Mongo shell}
		\scriptsize
		db.accounts.update(\\
		\{ name: t.source, pendingTransactions: \{ \$ne: t.\_id \} \},\\
		\{ \$inc: \{ balance: -t.value \}, \$push: \{ pendingTransactions: t.\_id \} \})\\
		db.accounts.update(\\
		\{ name: t.destination, pendingTransactions: \{ \$ne: t.\_id \} \},\\
		\{ \$inc: \{ balance: t.value \}, \$push: \{ pendingTransactions: t.\_id \} \})\\
	\end{alertblock}
\end{frame}

\begin{frame}
	\begin{block}{Update transaction state to committed}
		Use the following update() operation to set the transaction's state to committed

	\end{block}
	\pause
	\begin{alertblock}{Mongo shell}
		\scriptsize
		db.transactions.update(\{\_id: t.\_id\}, \{\$set: \{state: "committed"\}\})

	\end{alertblock}
\end{frame}

\begin{frame}
	\begin{block}{Update both accounts’ list of pending transactions}
		Remove the applied transaction \_id from the pendingTransactions array for both accounts.

	\end{block}
	\pause
	\begin{alertblock}{Mongo shell}
		\scriptsize
		db.accounts.update(\{name: t.source\}, \{\$pull: \{pendingTransactions: t.\_id\}\})

		db.accounts.update(\{name: t.destination\}, \{\$pull: \{pendingTransactions: t.\_id\}\})

		db.accounts.find()
	\end{alertblock}
\end{frame}

\begin{frame}
	\begin{block}{Update transaction state to done}
		Complete the transaction by setting the state of the transaction to done

	\end{block}
	\pause
	\begin{alertblock}{Mongo shell}
		\scriptsize
		db.transactions.update(\{\_id: t.\_id\}, \{\$set: \{state: "done"\}\})

		db.transactions.find()

	\end{alertblock}

\end{frame}
\begin{frame}
	\begin{block}{Recovery Operations}
The two-phase commit pattern allows applications running the sequence to resume the transaction and arrive at a consistent state. Run the recovery operations at application startup, and possibly at regular intervals, to catch any unfinished transactions.
	\end{block}
\end{frame}

\begin{frame}
	\begin{block}{Transactions in Pending State}
To recover from failures that occur after step “Update transaction state to pending.” but before “Update transaction state to applied.” step, retrieve from the transactions collection a pending transaction for recovery:
	\end{block}
	\pause
	\begin{alertblock}{Mongo shell}
		\scriptsize{
		var t = db.transactions.findOne( \{ state: "pending"\})
		}

	And resume from step "Apply the transaction to both accounts."
	\end{alertblock}
\end{frame}

\begin{frame}
	\begin{block}{Transactions in Applied State}
To recover from failures that occur after step “Update transaction state to applied.” but before “Update transaction state to done.” step, retrieve from the transactions collection an applied transaction for recovery:
	\end{block}
	\pause
	\begin{alertblock}{Mongo shell}
		\scriptsize{
		var t = db.transactions.findOne( \{ state: "committed"\})
		}

	And resume from "Update both accounts’ list of pending transactions."
	\end{alertblock}
\end{frame}

\begin{frame}
	\begin{block}{Rollback Operations}
In some cases, you may need to “roll back” or undo a transaction; e.g., if the application needs to “cancel” the transaction or if one of the accounts does not exist or stops existing during the transaction.
	\end{block}
\end{frame}

\begin{frame}
	\begin{block}{Transactions in Pending State}
		Update the transaction state from pending to canceling.
	\end{block}
	\pause
	\begin{alertblock}{Mongo shell}
		\scriptsize{
		db.transactions.update( \{ \_id: t.\_id, state: "pending" \}, \{ \$set: \{ state: "canceling" \} \}) 
		}
	\end{alertblock}
\end{frame}

\begin{frame}
	\begin{block}{Undo the transaction on both accounts}
Update the destination account, subtracting from its balance the transaction value and removing the transaction \_id from the pendingTransactions array.

	\end{block}
	\pause
	\begin{alertblock}{Mongo shell}
		\scriptsize{
db.accounts.update( \{ \_id: t.destination, pendingTransactions: t.\_id \}, \{ \$inc: \{ balance: -t.value \}, \$pull: \{ pendingTransactions: t.\_id \} \})

db.accounts.update( \{ \_id: t.source, pendingTransactions: t.\_id \}, \{ \$inc: \{ balance: t.value \}, \$pull: \{ pendingTransactions: t.\_id \} \})
		}
	\end{alertblock}
\end{frame}

\begin{frame}
	\begin{block}{Update transaction state to canceled.}
		To finish the rollback, update the transaction state from canceling to cancelled.
	\end{block}
	\pause
	\begin{alertblock}{Mongo shell}
		\scriptsize{
db.transactions.update(\{\_id: t.\_id, state: "canceling" \}, \{ \$set: \{ state: "cancelled" \}\})
}
	\end{alertblock}
\end{frame}
\end{document}


